package vaccine.appointment.system.appointmentrecord.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vaccine.appointment.system.appointmentrecord.dataobject.AppointmentRecord;
import vaccine.appointment.system.appointmentrecord.enums.AppointmentStatusEnum;
import vaccine.appointment.system.appointmentrecord.errorcode.AppointmentErrorCode;
import vaccine.appointment.system.appointmentrecord.mapper.AppointmentRecordMapper;
import vaccine.appointment.system.appointmentrecord.mq.OverdueReminderMessage;
import vaccine.appointment.system.appointmentrecord.service.AppointmentRecordService;
import vaccine.appointment.system.appointmentrecord.vo.AppointmentCalendarDayVO;
import vaccine.appointment.system.appointmentrecord.vo.AppointmentRecordVO;
import vaccine.appointment.system.appointmentrecord.vo.CreateAppointmentRequest;
import vaccine.appointment.system.appointmentrecord.vo.TodayAppointmentVO;
import vaccine.appointment.system.common.enums.DelFlgEnum;
import vaccine.appointment.system.common.errorcode.CommonErrorCode;
import vaccine.appointment.system.common.exception.CommonException;
import vaccine.appointment.system.family.dataobject.Family;
import vaccine.appointment.system.family.mapper.FamilyMapper;
import vaccine.appointment.system.inventory.dataobject.Inventory;
import vaccine.appointment.system.inventory.mapper.InventoryMapper;
import vaccine.appointment.system.person.dataobject.Person;
import vaccine.appointment.system.person.mapper.PersonMapper;
import vaccine.appointment.system.user.dataobject.User;
import vaccine.appointment.system.user.mapper.UserMapper;
import vaccine.appointment.system.vaccine.dataobject.Vaccine;
import vaccine.appointment.system.vaccine.mapper.VaccineMapper;
import vaccine.appointment.system.vaccinationsite.dataobject.VaccinationSite;
import vaccine.appointment.system.vaccinationsite.mapper.VaccinationSiteMapper;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class AppointmentRecordServiceImpl implements AppointmentRecordService {
    @Autowired
    private AppointmentRecordMapper appointmentRecordMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PersonMapper personMapper;

    @Autowired
    private FamilyMapper familyMapper;

    @Autowired
    private VaccineMapper vaccineMapper;

    @Autowired
    private VaccinationSiteMapper vaccinationSiteMapper;

    @Autowired
    private InventoryMapper inventoryMapper;

    @Override
    public void sendMessage(OverdueReminderMessage message) {
        //发送mq
    }

    /**
     * 创建预约
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createAppointment(Integer userId, CreateAppointmentRequest request) {
        // 1. 验证疫苗是否存在且未过期
        Vaccine vaccine = vaccineMapper.selectById(request.getVaccineId());
        if (vaccine == null || vaccine.getDelFlg().equals(DelFlgEnum.DELETED.getCode())) {
            throw new CommonException(CommonErrorCode.NOT_FOUND);
        }
        if (vaccine.getValidityPeriod().isBefore(LocalDate.now())) {
            throw new CommonException(AppointmentErrorCode.VACCINE_EXPIRED);
        }

        // 2. 验证接种点是否存在
        VaccinationSite site = vaccinationSiteMapper.selectById(request.getVaccinationSiteId());
        if (site == null || site.getDelFlg().equals(DelFlgEnum.DELETED.getCode())) {
            throw new CommonException(CommonErrorCode.NOT_FOUND);
        }

        // 3. 验证接种人是否属于当前用户或其家属
        User user = userMapper.selectById(userId);
        if (user == null || user.getDelFlg().equals(DelFlgEnum.DELETED.getCode())) {
            throw new CommonException(CommonErrorCode.NOT_FOUND);
        }

        boolean isAuthorized = false;
        if (user.getPersonId() != null && user.getPersonId().equals(request.getPersonId())) {
            isAuthorized = true;
        } else {
            QueryWrapper<Family> familyQueryWrapper = new QueryWrapper<>();
            familyQueryWrapper.eq("user_id", userId);
            familyQueryWrapper.eq("person_id", request.getPersonId());
            familyQueryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());
            Family family = familyMapper.selectOne(familyQueryWrapper);
            if (family != null) {
                isAuthorized = true;
            }
        }
        if (!isAuthorized) {
            throw new CommonException(AppointmentErrorCode.PERSON_NOT_AUTHORIZED);
        }

        // 4. 使用悲观锁查询库存（FOR UPDATE）
        Inventory inventory = inventoryMapper.selectForUpdate(
            request.getVaccineId(),
            request.getVaccinationSiteId()
        );

        if (inventory == null || inventory.getCount() <= 0) {
            throw new CommonException(AppointmentErrorCode.VACCINE_OUT_OF_STOCK);
        }

        // 5. 原子性扣减库存
        int decreaseResult = inventoryMapper.decreaseStock(inventory.getId(), 1);
        if (decreaseResult <= 0) {
            throw new CommonException(AppointmentErrorCode.VACCINE_OUT_OF_STOCK);
        }

        // 6. 创建预约记录
        AppointmentRecord record = new AppointmentRecord();
        record.setPersonId(request.getPersonId());
        record.setVaccineId(request.getVaccineId());
        record.setVaccinationSiteId(request.getVaccinationSiteId());
        record.setAppointmentTime(request.getAppointmentTime());
        record.setAppointmentStatus(AppointmentStatusEnum.APPOINTED.getCode());
        record.setDelFlg(DelFlgEnum.NOT_DELETED.getCode());

        int result = appointmentRecordMapper.insert(record);
        return result > 0;
    }

    /**
     * 查询预约记录列表
     */
    @Override
    public Page<AppointmentRecordVO> getAppointmentList(Integer userId, Integer status, Integer pageNum, Integer pageSize) {
        // 1. 获取用户及其家属的personId列表
        User user = userMapper.selectById(userId);
        List<Integer> personIds = new ArrayList<>();
        personIds.add(user.getPersonId());

        QueryWrapper<Family> familyQueryWrapper = new QueryWrapper<>();
        familyQueryWrapper.eq("user_id", userId);
        familyQueryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());
        List<Family> familyList = familyMapper.selectList(familyQueryWrapper);
        for (Family family : familyList) {
            personIds.add(family.getPersonId());
        }

        // 2. 查询预约记录
        Page<AppointmentRecord> page = new Page<>(pageNum, pageSize);
        QueryWrapper<AppointmentRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("person_id", personIds);
        queryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());
        if (status != null) {
            queryWrapper.eq("appointment_status", status);
        }
        queryWrapper.orderByDesc("appointment_time");

        Page<AppointmentRecord> recordPage = appointmentRecordMapper.selectPage(page, queryWrapper);

        // 3. 组装VO
        Page<AppointmentRecordVO> voPage = new Page<>(pageNum, pageSize);
        voPage.setTotal(recordPage.getTotal());

        List<AppointmentRecordVO> voList = new ArrayList<>();
        for (AppointmentRecord record : recordPage.getRecords()) {
            AppointmentRecordVO vo = convertToVO(record);
            voList.add(vo);
        }
        voPage.setRecords(voList);

        return voPage;
    }

    /**
     * 取消预约
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean cancelAppointment(Integer userId, Integer appointmentId) {
        // 1. 查询预约记录
        AppointmentRecord record = appointmentRecordMapper.selectById(appointmentId);
        if (record == null || record.getDelFlg().equals(DelFlgEnum.DELETED.getCode())) {
            throw new CommonException(AppointmentErrorCode.APPOINTMENT_NOT_FOUND);
        }

        // 2. 验证权限
        User user = userMapper.selectById(userId);
        boolean isAuthorized = false;
        if (user.getPersonId().equals(record.getPersonId())) {
            isAuthorized = true;
        } else {
            QueryWrapper<Family> familyQueryWrapper = new QueryWrapper<>();
            familyQueryWrapper.eq("user_id", userId);
            familyQueryWrapper.eq("person_id", record.getPersonId());
            familyQueryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());
            Family family = familyMapper.selectOne(familyQueryWrapper);
            if (family != null) {
                isAuthorized = true;
            }
        }
        if (!isAuthorized) {
            throw new CommonException(CommonErrorCode.FORBIDDEN);
        }

        // 3. 验证状态
        if (!record.getAppointmentStatus().equals(AppointmentStatusEnum.APPOINTED.getCode())) {
            throw new CommonException(AppointmentErrorCode.APPOINTMENT_CANNOT_CANCEL);
        }

        // 4. 更新状态为已取消（逻辑删除，不恢复库存）
        // 注意：用户取消预约不恢复库存，只有管理员可以操作库存
        record.setAppointmentStatus(AppointmentStatusEnum.CANCELLED.getCode());
        appointmentRecordMapper.updateById(record);

        // 5. 不恢复库存（用户取消预约时，库存由管理员管理）
        // 如果将来需要恢复库存，应该由管理员在管理界面操作

        return true;
    }

    /**
     * 查询逾期未接种的预约记录
     */
    @Override
    public List<AppointmentRecordVO> getOverdueAppointments(Integer userId) {
        // 1. 获取用户及其家属的personId列表
        User user = userMapper.selectById(userId);
        List<Integer> personIds = new ArrayList<>();
        personIds.add(user.getPersonId());

        QueryWrapper<Family> familyQueryWrapper = new QueryWrapper<>();
        familyQueryWrapper.eq("user_id", userId);
        familyQueryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());
        List<Family> familyList = familyMapper.selectList(familyQueryWrapper);
        for (Family family : familyList) {
            personIds.add(family.getPersonId());
        }

        // 2. 查询逾期预约（预约时间早于今天且状态为已预约）
        QueryWrapper<AppointmentRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("person_id", personIds);
        queryWrapper.eq("appointment_status", AppointmentStatusEnum.APPOINTED.getCode());
        queryWrapper.lt("appointment_time", LocalDate.now());
        queryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());
        queryWrapper.orderByDesc("appointment_time");

        List<AppointmentRecord> records = appointmentRecordMapper.selectList(queryWrapper);

        // 3. 组装VO
        List<AppointmentRecordVO> voList = new ArrayList<>();
        for (AppointmentRecord record : records) {
            AppointmentRecordVO vo = convertToVO(record);
            voList.add(vo);
        }

        return voList;
    }

    /**
     * 转换为VO
     */
    private AppointmentRecordVO convertToVO(AppointmentRecord record) {
        AppointmentRecordVO vo = new AppointmentRecordVO();
        vo.setId(record.getId());
        vo.setAppointmentTime(record.getAppointmentTime());
        vo.setAppointmentStatus(record.getAppointmentStatus());
        vo.setAppointmentStatusDesc(AppointmentStatusEnum.getDescByCode(record.getAppointmentStatus()));

        // 查询接种人信息
        Person person = personMapper.selectById(record.getPersonId());
        if (person != null) {
            vo.setPersonName(person.getName());
            vo.setPersonIdNum(person.getIdNum());
        }

        // 查询疫苗信息
        Vaccine vaccine = vaccineMapper.selectById(record.getVaccineId());
        if (vaccine != null) {
            vo.setVaccineName(vaccine.getName());
            if (vaccine.getType() != null) {
                vo.setVaccineType(String.valueOf(vaccine.getType()));
            }
        }

        // 查询接种点信息
        VaccinationSite site = vaccinationSiteMapper.selectById(record.getVaccinationSiteId());
        if (site != null) {
            vo.setVaccinationSiteName(site.getName());
            vo.setVaccinationSiteAddress(site.getAddress());
        }

        return vo;
    }

    /**
     * 查询当日预约列表（管理员功能）
     */
    @Override
    public Page<TodayAppointmentVO> getTodayAppointments(Integer vaccinationSiteId, Integer status, Integer pageNum, Integer pageSize) {
        Page<AppointmentRecord> page = new Page<>(pageNum, pageSize);
        QueryWrapper<AppointmentRecord> queryWrapper = new QueryWrapper<>();

        // 查询指定接种点的预约
        if (vaccinationSiteId != null) {
            queryWrapper.eq("vaccination_site_id", vaccinationSiteId);
        }

        // 查询当日预约
        queryWrapper.eq("appointment_time", LocalDate.now());
        queryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());
        
        // 过滤掉已取消的预约（接种点管理员不显示已取消的预约）
        queryWrapper.ne("appointment_status", AppointmentStatusEnum.CANCELLED.getCode());

        // 状态筛选
        if (status != null) {
            queryWrapper.eq("appointment_status", status);
        }

        queryWrapper.orderByAsc("appointment_status");
        queryWrapper.orderByDesc("id");

        Page<AppointmentRecord> recordPage = appointmentRecordMapper.selectPage(page, queryWrapper);

        // 组装VO
        Page<TodayAppointmentVO> voPage = new Page<>(pageNum, pageSize);
        voPage.setTotal(recordPage.getTotal());

        List<TodayAppointmentVO> voList = new ArrayList<>();
        for (AppointmentRecord record : recordPage.getRecords()) {
            TodayAppointmentVO vo = convertToTodayVO(record);
            voList.add(vo);
        }
        voPage.setRecords(voList);

        return voPage;
    }

    @Override
    public List<TodayAppointmentVO> getAppointmentsByDate(Integer vaccinationSiteId, LocalDate date) {
        if (date == null) {
            date = LocalDate.now();
        }
        QueryWrapper<AppointmentRecord> queryWrapper = new QueryWrapper<>();
        if (vaccinationSiteId != null) {
            queryWrapper.eq("vaccination_site_id", vaccinationSiteId);
        }
        queryWrapper.eq("appointment_time", date);
        queryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());
        
        // 过滤掉已取消的预约（接种点管理员不显示已取消的预约）
        queryWrapper.ne("appointment_status", AppointmentStatusEnum.CANCELLED.getCode());
        
        queryWrapper.orderByAsc("appointment_status");
        queryWrapper.orderByDesc("id");

        List<AppointmentRecord> records = appointmentRecordMapper.selectList(queryWrapper);
        List<TodayAppointmentVO> voList = new ArrayList<>();
        for (AppointmentRecord record : records) {
            voList.add(convertToTodayVO(record));
        }
        return voList;
    }

    @Override
    public List<AppointmentCalendarDayVO> getMonthlySummary(Integer vaccinationSiteId, LocalDate month) {
        LocalDate targetMonth = month != null ? month.withDayOfMonth(1) : LocalDate.now().withDayOfMonth(1);
        LocalDate monthEnd = targetMonth.plusMonths(1).minusDays(1);

        QueryWrapper<AppointmentRecord> queryWrapper = new QueryWrapper<>();
        if (vaccinationSiteId != null) {
            queryWrapper.eq("vaccination_site_id", vaccinationSiteId);
        }
        queryWrapper.between("appointment_time", targetMonth, monthEnd);
        queryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());

        List<AppointmentRecord> records = appointmentRecordMapper.selectList(queryWrapper);
        Map<LocalDate, AppointmentCalendarDayVO> summaryMap = new HashMap<>();

        for (AppointmentRecord record : records) {
            LocalDate date = record.getAppointmentTime();
            AppointmentCalendarDayVO vo = summaryMap.computeIfAbsent(date, key -> {
                AppointmentCalendarDayVO item = new AppointmentCalendarDayVO();
                item.setDate(key);
                item.setTotalCount(0);
                item.setPendingCount(0);
                item.setCompletedCount(0);
                item.setCancelledCount(0);
                return item;
            });

            vo.setTotalCount(vo.getTotalCount() + 1);
            if (AppointmentStatusEnum.APPOINTED.getCode() == record.getAppointmentStatus()) {
                vo.setPendingCount(vo.getPendingCount() + 1);
            } else if (AppointmentStatusEnum.COMPLETED.getCode() == record.getAppointmentStatus()) {
                vo.setCompletedCount(vo.getCompletedCount() + 1);
            } else if (AppointmentStatusEnum.CANCELLED.getCode() == record.getAppointmentStatus()) {
                vo.setCancelledCount(vo.getCancelledCount() + 1);
            }
        }

        return new ArrayList<>(summaryMap.values());
    }

    /**
     * 更新预约状态（管理员功能）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateAppointmentStatus(Integer appointmentId, Integer status, Integer vaccinationSiteId) {
        // 1. 查询预约记录
        AppointmentRecord record = appointmentRecordMapper.selectById(appointmentId);
        if (record == null || record.getDelFlg().equals(DelFlgEnum.DELETED.getCode())) {
            throw new CommonException(AppointmentErrorCode.APPOINTMENT_NOT_FOUND);
        }

        // 2. 验证权限（如果指定了接种点ID，则验证预约是否属于该接种点）
        if (vaccinationSiteId != null && !record.getVaccinationSiteId().equals(vaccinationSiteId)) {
            throw new CommonException(CommonErrorCode.FORBIDDEN);
        }

        // 3. 更新状态
        Integer oldStatus = record.getAppointmentStatus();
        record.setAppointmentStatus(status);
        appointmentRecordMapper.updateById(record);

        // 4. 如果从已预约改为已取消，需要原子性恢复库存
        if (oldStatus.equals(AppointmentStatusEnum.APPOINTED.getCode())
            && status.equals(AppointmentStatusEnum.CANCELLED.getCode())) {
            QueryWrapper<Inventory> inventoryQueryWrapper = new QueryWrapper<>();
            inventoryQueryWrapper.eq("vaccine_id", record.getVaccineId());
            inventoryQueryWrapper.eq("vaccination_site_id", record.getVaccinationSiteId());
            inventoryQueryWrapper.eq("del_flg", DelFlgEnum.NOT_DELETED.getCode());
            Inventory inventory = inventoryMapper.selectOne(inventoryQueryWrapper);

            if (inventory != null) {
                inventoryMapper.increaseStock(inventory.getId(), 1);
            }
        }

        return true;
    }

    /**
     * 转换为当日预约VO
     */
    private TodayAppointmentVO convertToTodayVO(AppointmentRecord record) {
        TodayAppointmentVO vo = new TodayAppointmentVO();
        vo.setId(record.getId());
        vo.setAppointmentTime(record.getAppointmentTime());
        vo.setAppointmentStatus(record.getAppointmentStatus());
        vo.setAppointmentStatusDesc(AppointmentStatusEnum.getDescByCode(record.getAppointmentStatus()));

        // 查询接种人信息
        Person person = personMapper.selectById(record.getPersonId());
        if (person != null) {
            vo.setPersonName(person.getName());
            vo.setPersonIdNum(person.getIdNum());
            vo.setPersonAge(person.getAge());
        }

        // 查询疫苗信息
        Vaccine vaccine = vaccineMapper.selectById(record.getVaccineId());
        if (vaccine != null) {
            vo.setVaccineName(vaccine.getName());
            if (vaccine.getType() != null) {
                vo.setVaccineType(String.valueOf(vaccine.getType()));
            }
        }

        return vo;
    }
}

